﻿using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;

namespace VkSample96
{
    public class LandData
    {
        /// <summary>
        /// 顶点数
        /// </summary>
        public uint VCount { get; set; }

        private Vector3[] vertices;
        private Vector3[] normals;
        private float xStart;
        private float zStart;
        private float[,] gdz;
        private int rows;
        private int cols;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public float[] GenData(int width, int height, byte[] heightData)
        {
            gdz = new float[height, width];
            for(int i = 0; i < height; i++)
            {
                for(int j = 0; j < width; j++)
                {
                    int h = heightData[i * width + j];
                    gdz[i, j] = h * 198 / 255.0f + 0;
                }
            }
            int landSpan = 1;
            rows = height - 1;
            cols = width - 1;
            int gzCount = rows * cols;
            VCount = (uint)gzCount * 2 * 3;
            float[] vData = new float[VCount * 8];
            xStart = -landSpan * cols / 2.0f;
            zStart = -landSpan * rows / 2.0f;
            float sSpan = 1.0f / cols;
            float tSpan = 1.0f / rows;
            CalNormals(width, height);
            int indexTemp = 0; //辅助索引
            for(int i = 0; i < cols; i++)
            {
                for(int j = 0; j < rows; j++)
                {
                    float s0 = sSpan * j;
                    float t0 = tSpan * i;
                    float s1 = sSpan * (j + 1);
                    float t1 = tSpan * i;
                    float s2 = sSpan * j;
                    float t2 = tSpan * (i + 1);
                    float s3 = sSpan * (j + 1);
                    float t3 = tSpan * (i + 1);

                    vData[indexTemp++] = vertices[i * width + j].X;
                    vData[indexTemp++] = vertices[i * width + j].Y;
                    vData[indexTemp++] = vertices[i * width + j].Z;
                    vData[indexTemp++] = s0;
                    vData[indexTemp++] = t0;
                    vData[indexTemp++] = normals[i * width + j].X;
                    vData[indexTemp++] = normals[i * width + j].Y;
                    vData[indexTemp++] = normals[i * width + j].Z;

                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].X;
                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].Y;
                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].Z;
                    vData[indexTemp++] = s3;
                    vData[indexTemp++] = t3;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].X;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].Y;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].Z;

                    vData[indexTemp++] = vertices[i * width + j + 1].X;
                    vData[indexTemp++] = vertices[i * width + j + 1].Y;
                    vData[indexTemp++] = vertices[i * width + j + 1].Z;
                    vData[indexTemp++] = s1;
                    vData[indexTemp++] = t1;
                    vData[indexTemp++] = normals[i * width + j + 1].X;
                    vData[indexTemp++] = normals[i * width + j + 1].Y;
                    vData[indexTemp++] = normals[i * width + j + 1].Z;

                    vData[indexTemp++] = vertices[i * width + j].X;
                    vData[indexTemp++] = vertices[i * width + j].Y;
                    vData[indexTemp++] = vertices[i * width + j].Z;
                    vData[indexTemp++] = s0;
                    vData[indexTemp++] = t0;
                    vData[indexTemp++] = normals[i * width + j].X;
                    vData[indexTemp++] = normals[i * width + j].Y;
                    vData[indexTemp++] = normals[i * width + j].Z;

                    vData[indexTemp++] = vertices[(i + 1) * width + j].X;
                    vData[indexTemp++] = vertices[(i + 1) * width + j].Y;
                    vData[indexTemp++] = vertices[(i + 1) * width + j].Z;
                    vData[indexTemp++] = s2;
                    vData[indexTemp++] = t2;
                    vData[indexTemp++] = normals[(i + 1) * width + j].X;
                    vData[indexTemp++] = normals[(i + 1) * width + j].Y;
                    vData[indexTemp++] = normals[(i + 1) * width + j].Z;

                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].X;
                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].Y;
                    vData[indexTemp++] = vertices[(i + 1) * width + j + 1].Z;
                    vData[indexTemp++] = s3;
                    vData[indexTemp++] = t3;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].X;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].Y;
                    vData[indexTemp++] = normals[(i + 1) * width + j + 1].Z;
                }
            }
            return vData;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void CalNormals(int width, int height)
        {
            vertices = new Vector3[width * height];
            normals = new Vector3[width * height];
            for(int i = 0; i < height; i++)
            {
                for(int j = 0; j < width; j++)
                {
                    vertices[i * width + j] = new Vector3(xStart + j * 1, gdz[i, j], zStart + i * 1);
                }
            }
            int[] index = new int[4];
            for(int i = 0; i < rows; i++)
            {
                for(int j = 0; j < cols; j++)
                {
                    index[0] = i * width + j;
                    index[1] = index[0] + 1;
                    index[2] = index[0] + width;
                    index[3] = index[2] + 1;
                    Vector3 va = vertices[index[3]] - vertices[index[0]];
                    Vector3 vb = vertices[index[1]] - vertices[index[0]];
                    Vector3 normal = Vector3.Normalize(Vector3.Cross(va, vb));
                    for(int k = 0; k < 4; k++)
                    {
                        if (k == 2) continue;
                        normals[index[k]] += normal;
                    }
                    va = vertices[index[2]] - vertices[index[0]];
                    vb = vertices[index[3]] - vertices[index[0]];
                    normal = Vector3.Normalize(Vector3.Cross(va, vb));
                    for(int k = 0; k < 4; k++)
                    {
                        if (k == 1) continue;
                        normals[index[k]] += normal;
                    }
                }
            }
        }
    }
}
